package game.objects;
import java.io.Serializable;

import physics.PhysicalConstants;
import physics.joints.JAngleJoint;
import tools.Floatmath;
import tools.Help;
import tools.Point;
public class Kinematics implements Serializable {
	public enum AnimState {
		WALKRIGHT, WALKLEFT, STAND, JUMP;
	}
	private static final float STRIDEFREQUENCY = 7f;
	private static final float MAXUPPERLEGANGLE = 1.8f;
	private Figure figure;
	private AnimState state;
	private float stateTime;
	public float headAngle;
	public float rLegUpAngle;
	public float rLegDownAngle;
	public float rFootAngle;
	public float lLegUpAngle;
	public float lLegDownAngle;
	public float lFootAngle;
	public float rArmUpAngle;
	public float rArmDownAngle;
	public float rHandAngle;
	public float lArmUpAngle;
	public float lArmDownAngle;
	public float lHandAngle;
	public Kinematics(Figure figure) {
		state = AnimState.STAND;
		this.figure = figure;
	}
	public void setWalkingDir(float d) {
		rArmDownAngle = d * Floatmath.PIHALF * 0.9f;
		lArmDownAngle = d * Floatmath.PIHALF * 0.9f;
	}
	public void handle() {
		switch (state) {
			case WALKRIGHT :
				stateTime -= PhysicalConstants.DT;
				rLegUpAngle = Floatmath.sin(stateTime * STRIDEFREQUENCY) * MAXUPPERLEGANGLE - 0.3f;
				lLegUpAngle = -Floatmath.sin(stateTime * STRIDEFREQUENCY) * MAXUPPERLEGANGLE - 0.3f;
				rLegDownAngle = Math.max((Floatmath.cos(stateTime * STRIDEFREQUENCY) * 2), 0);
				lLegDownAngle = Math.max(-(Floatmath.cos(stateTime * STRIDEFREQUENCY) * 2), 0);
				rFootAngle = (Floatmath.sin(stateTime * STRIDEFREQUENCY) * 1);
				lFootAngle = -(Floatmath.sin(stateTime * STRIDEFREQUENCY) * 1);
				break;
			case WALKLEFT : {
				stateTime += PhysicalConstants.DT;
				rLegUpAngle = Floatmath.sin(stateTime * STRIDEFREQUENCY) * MAXUPPERLEGANGLE - 0.3f;
				lLegUpAngle = -Floatmath.sin(stateTime * STRIDEFREQUENCY) * MAXUPPERLEGANGLE - 0.3f;
				rLegDownAngle = Math.max((Floatmath.cos(stateTime * STRIDEFREQUENCY) * 2), 0);
				lLegDownAngle = Math.max(-(Floatmath.cos(stateTime * STRIDEFREQUENCY) * 2), 0);
				rFootAngle = -(Floatmath.sin(stateTime * STRIDEFREQUENCY) * 1);
				lFootAngle = (Floatmath.sin(stateTime * STRIDEFREQUENCY) * 1);
				break;
			}
			case STAND :
				rLegUpAngle = 0;
				lLegUpAngle = 0;
				rLegDownAngle = 0;
				lLegDownAngle = 0;
				rFootAngle = 0;
				lFootAngle = 0;
				stateTime = 0;
				break;
			case JUMP :
				stateTime = 0;
				rLegUpAngle = 0;
				lLegUpAngle = 0;
				rLegDownAngle = 0.5f;
				lLegDownAngle = 0.5f;
				rFootAngle = 1.5f;
				lFootAngle = 1.5f;
				break;
		}
		apply();
	}
	private void apply() {
		figure.headAngle.setAngle(headAngle);
		figure.rLegUpAngle.setAngle(rLegUpAngle);
		figure.rLegDownAngle.setAngle(rLegDownAngle);
		figure.rFootAngle.setAngle(rFootAngle);
		figure.lLegUpAngle.setAngle(lLegUpAngle);
		figure.lLegDownAngle.setAngle(lLegDownAngle);
		figure.lFootAngle.setAngle(lFootAngle);
		figure.rArmUpAngle.setAngle(rArmUpAngle);
		figure.rArmDownAngle.setAngle(rArmDownAngle);
		figure.rHandAngle.setAngle(rHandAngle);
		figure.lArmUpAngle.setAngle(lArmUpAngle);
		figure.lArmDownAngle.setAngle(lArmDownAngle);
		figure.lHandAngle.setAngle(lHandAngle);
	}
	public AnimState getState() {
		return state;
	}
	public void setState(AnimState state) {
		this.state = state;
	}
	public void lookAt(Point mp) {
		float a = mp.sub(figure.head.pos).angle();
		if (-0.8f < a && a < 1.2f) {
			headAngle = -a;
		}
	}
}
